package com.lej.core.base

import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.annotation.LayoutRes
import androidx.databinding.DataBindingUtil
import androidx.databinding.ViewDataBinding
import androidx.fragment.app.Fragment
import androidx.lifecycle.*
import com.lej.core.utils.KLog
import com.qmuiteam.qmui.widget.dialog.QMUITipDialog
import java.lang.reflect.ParameterizedType

abstract class BaseFragment<V : ViewDataBinding, VM : BaseViewModel<*>> :
    Fragment(), IBaseView {
    lateinit var binding: V
    lateinit var viewModel: VM
    private var viewModelId = 0
    private var tipDialog: QMUITipDialog? = null//提示dialog

    fun isBindingInitialized() = ::binding.isInitialized
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        initParam()
    }

    override fun onCreateView(
        inflater: LayoutInflater,
        container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View? {
        binding = DataBindingUtil.inflate(inflater, getLayout(), container, false)
        return binding.root
    }

    override fun onDestroyView() {
        super.onDestroyView()
        binding.unbind()
    }

    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)
        //私有的初始化DataBinding和ViewModel方法
        initViewDataBinding()
        //私有的ViewModel与View的契约事件回调逻辑
        registerUIChangeLiveDataCallBack()
        //页面数据初始化方法
        initData()
        //页面事件监听的方法，一般用于ViewModel层转到View层的事件注册
        initViewObservable()
    }

    /**
     * 注入绑定
     */
    @Suppress("UNCHECKED_CAST")
    private fun initViewDataBinding() {
        viewModelId = initVariableId()
        initViewModel()?.let { viewModel = it }

        if (!::viewModel.isInitialized) {
            val modelClass: Class<ViewModel>
            val type = javaClass.genericSuperclass
            modelClass = if (type is ParameterizedType) {
                type.actualTypeArguments[1] as Class<ViewModel>
            } else {
                //如果没有指定泛型参数，则默认使用BaseViewModel
                BaseViewModel::class.java as Class<ViewModel>
            }
            viewModel = createViewModel(modelClass) as VM
        }
        binding.setVariable(viewModelId, viewModel)
        binding.lifecycleOwner = this
        //让ViewModel拥有View的生命周期感应
        (viewModel as? LifecycleObserver)?.let { lifecycle.addObserver(it) }
        //注入RxLifecycle生命周期
        viewModel.injectLifecycleProvider(this)
    }

    /*=====================================================================*/ //注册ViewModel与View的契约UI回调事件
    protected fun registerUIChangeLiveDataCallBack() {
        viewModel.uC.run {
            //加载对话框显示
            showDialogEvent?.addObserver(::showLoading)
            //加载对话框消失
            dismissDialogEvent?.addObserver { hideLoading() }
            //关闭界面
            finishEvent?.addObserver { activity?.finish() }
            //关闭上一层
            onBackPressedEvent?.addObserver { activity?.onBackPressed() }
        }
    }

    @JvmOverloads
    fun showLoading(tips: String? = null) {
        val activity = activity
        if (activity == null) {
            KLog.e("the activity is null")
            return
        }
        if (tipDialog?.isShowing == true) tipDialog?.dismiss()
        tipDialog = QMUITipDialog.Builder(activity)
            .setIconType(QMUITipDialog.Builder.ICON_TYPE_LOADING)
            .setTipWord(tips)
            .create()
        tipDialog?.setCancelable(false)
        tipDialog?.show()
    }

    fun hideLoading() {
        if (tipDialog?.isShowing == true) {
            tipDialog?.dismiss()
        }
    }

    //刷新布局
    fun refreshLayout() {
        binding.setVariable(viewModelId, viewModel)
    }

    override fun initParam() {}

    /**
     * 初始化根布局
     *
     * @return 布局layout的id
     */
    @LayoutRes
    abstract fun getLayout(): Int

    /**
     * 初始化ViewModel的id
     *
     * @return BR的id
     */
    abstract fun initVariableId(): Int

    /**
     * 初始化ViewModel
     *
     * @return 继承BaseViewModel的ViewModel
     */
    open fun initViewModel(): VM? {
        return null
    }

    override fun initData() {}
    override fun initViewObservable() {}
    val isBackPressed: Boolean get() = false

    /**
     * 创建ViewModel
     *
     * @param cls
     * @param <T>
     * @return
    </T> */
    fun <T : ViewModel> ViewModelStoreOwner.createViewModel(cls: Class<T>) =
        ViewModelProvider(this).get(cls)

    protected fun <T> LiveData<T>.addObserver(observer: Observer<T>) {
        observe(viewLifecycleOwner, observer)
    }
}